package com.hrzyit.base.utils.digest

import android.content.Context
import android.content.pm.PackageManager
import java.util.*
import javax.crypto.*
import javax.crypto.spec.SecretKeySpec

/**
 * AES 加密工具类
 */
object AESUtils {
    private const val ALGORITHM = "AES"
    private const val TRANSFORMATION = "AES"
    /**
     * Encrypts a password.
     * @param input The password to be encrypted.
     * @param seed The seed.
     * @return Encrypted password.
     */
    @JvmStatic
    @Throws(Exception::class)
    fun encrypt(input: ByteArray, seed: ByteArray): String {
        val key = getRawKey(Arrays.copyOf(seed, 16))
        val result = toEncrypt(key, input)
        return Base64Util.encode(result)
    }

    /**
     * Encrypts a password.
     * @param input The password to be encrypted.
     * @param seed The seed.
     * @return Encrypted password.
     */
    @JvmStatic
    @Throws(Exception::class)
    fun encrypt(input: String, seed: ByteArray): String {
        val key = getRawKey(Arrays.copyOf(seed, 16))
        val result = toEncrypt(key, input.toByteArray())
        return Base64Util.encode(result)
    }

    /**
     * Encrypts a password.
     * @param input The password to be encrypted.
     * @param seed The seed.
     * @return Encrypted password.
     */
    @JvmStatic
    @Throws(Exception::class)
    fun encrypt(input: ByteArray, seed: String): String {
        val key = getRawKey(Arrays.copyOf(seed.toByteArray(), 16))
        val result = toEncrypt(key, input)
        return Base64Util.encode(result)
    }

    /**
     * Encrypts a password.
     * @param input The password to be encrypted.
     * @param seed The seed.
     * @return Encrypted password.
     */
    @JvmStatic
    @Throws(Exception::class)
    fun encrypt(input: String, seed: String): String {
        val key = getRawKey(Arrays.copyOf(seed.toByteArray(), 16))
        val result = toEncrypt(key, input.toByteArray())
        return Base64Util.encode(result)
    }

    /**
     * Decrypt a password.
     * @param input The password to be decrypted.
     * @param seed The seed.
     * @return Decrypted password.
     */
    @JvmStatic
    @Throws(Exception::class)
    fun decrypt(input: ByteArray, seed: ByteArray): String {
        val key = getRawKey(Arrays.copyOf(seed, 16))
        val encrypted = Base64Util.decode(input)
        val result = toDecrypt(key, encrypted)
        return String(result)
    }

    /**
     * Decrypt a password.
     * @param input The password to be decrypted.
     * @param seed The seed.
     * @return Decrypted password.
     */
    @JvmStatic
    @Throws(Exception::class)
    fun decrypt(input: String, seed: ByteArray): String {
        val key = getRawKey(Arrays.copyOf(seed, 16))
        val encrypted = Base64Util.decode(input)
        val result = toDecrypt(key, encrypted)
        return String(result)
    }

    /**
     * Decrypt a password.
     * @param input The password to be decrypted.
     * @param seed The seed.
     * @return Decrypted password.
     */
    @JvmStatic
    @Throws(Exception::class)
    fun decrypt(input: ByteArray, seed: String): String {
        val key = getRawKey(Arrays.copyOf(seed.toByteArray(), 16))
        val encrypted = Base64Util.decode(input)
        val result = toDecrypt(key, encrypted)
        return String(result)
    }

    /**
     * Decrypt a password.
     * @param input The password to be decrypted.
     * @param seed The seed.
     * @return Decrypted password.
     */
    @JvmStatic
    @Throws(Exception::class)
    fun decrypt(input: String, seed: String): String {
        val key = getRawKey(Arrays.copyOf(seed.toByteArray(), 16))
        val encrypted = Base64Util.decode(input)
        val result = toDecrypt(key, encrypted)
        return String(result)
    }

    @Throws(Exception::class)
    private fun getRawKey(seed: ByteArray): SecretKey = SecretKeySpec(seed, ALGORITHM)

    @Throws(Exception::class)
    private fun toEncrypt(key: SecretKey, input: ByteArray): ByteArray {
        val cipher = Cipher.getInstance(TRANSFORMATION)
        cipher.init(Cipher.ENCRYPT_MODE, key)
        return cipher.doFinal(input)
    }

    @Throws(Exception::class)
    private fun toDecrypt(key: SecretKey, encrypted: ByteArray): ByteArray {
        val cipher = Cipher.getInstance(TRANSFORMATION)
        cipher.init(Cipher.DECRYPT_MODE, key)
        return cipher.doFinal(encrypted)
    }

    /**
     * 根据包名生成加密key
     * @param paramContext  上下文对象
     * @return ByteArray
     */
    @JvmStatic
    @Throws(PackageManager.NameNotFoundException::class)
    fun generatePassword(paramContext: Context): ByteArray {
        val l = paramContext.packageManager
                .getPackageInfo(paramContext.packageName, PackageManager.GET_META_DATA)
                .firstInstallTime
        val packageName = paramContext.packageName
        return (l.toString() + packageName).toByteArray()
    }
}

